package com.lsa.skienna.challenge.chap9.the110904_SlashMaze;

import static org.junit.Assert.assertEquals;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.Random;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.junit.Test;

import com.lsa.skienna.challenge.chap9.the110904_SlashMaze.Main.graph;

public class TestSlashMaze {

	public void testCycleDetector() {
		graph g = new graph();
		g.nvertices = 10;
		g.insert_edge(1, 2, false);
		g.insert_edge(1, 4, false);
		g.insert_edge(2, 4, false);
		g.insert_edge(4, 3, false);
		g.insert_edge(3, 1, false);
		
		g.insert_edge(5, 6, false);
		g.insert_edge(6, 7, false);
		g.insert_edge(7, 8, false);
		g.insert_edge(8, 9, false);
		g.insert_edge(9, 10, false);
		g.insert_edge(10, 5, false);
		
		Main.initialize_search(g);
		Main.findCycles(g);
		Main.reportCycles();
	}
	
	@Test
	public void testOnInput() throws IOException {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		Main.process(new FileInputStream("data/pc9/slashMaze/110904.inp"), new PrintStream(out));
		String expected = FileUtils.readFileToString(new File("data/pc9/slashMaze/110904.oup"));
		assertEquals(expected, out.toString());
		System.out.println(out.toString());
	}
	
	@Test
	public void testOnInput2() throws IOException {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		Main.process(new FileInputStream("data/pc9/slashMaze/6.inp"), new PrintStream(out));
		String expected = FileUtils.readFileToString(new File("data/pc9/slashMaze/6.oup"));
		assertEquals(expected, out.toString());
		System.out.println(out.toString());
	}
	
//	@Test
	public void testOnRandom() throws IOException {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		StringBuilder mazesSb = generateRandomMazes(100, 50, 75, 75);
		String randomTestFile = "data/pc9/slashMaze/random.inp";
		FileUtils.write(new File(randomTestFile), mazesSb);
		Main.process(new FileInputStream(randomTestFile), new PrintStream(out));
		System.out.println(out.toString());
		String expected = invokeExe("data/pc9/slashMaze/invokeMain.cmd", randomTestFile);
		assertEquals(expected, out.toString());
		System.out.println(expected);
	}
	
	private StringBuilder generateRandomMazes(int mazeNumber, int lowBound, int maxW, int maxH) {
		StringBuilder sb = new StringBuilder();
		
		for (int i = 0; i < mazeNumber; i++) {
			int w = random(lowBound, maxW);
			int h = random(lowBound, maxW);
			sb.append(w + " " + h + "\n");
			
			for (int l = 0; l < h; l++) {
				for (int k = 0; k < w; k++) {
					boolean isForward = random(1, 10) > 5;
					sb.append(isForward? "/" : "\\");
				}
				sb.append("\n");
			}
		}
		
		sb.append("0 0\n");
		
		return sb;
	}
	
	String invokeExe(String exePath, String inputFilePath) throws IOException {
		Runtime r = Runtime.getRuntime();
        Process p = r.exec(new File(exePath).getAbsolutePath() , null, new File(inputFilePath).getParentFile());
		String s = inputStreamToString(p.getInputStream(), 2);
		String err = inputStreamToString(p.getErrorStream(),0);
        return s + err;
	}

	public String inputStreamToString(InputStream inputStream, int linesToSkip)
			throws IOException {
		BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String line = null;
        int lineNumber = 0;
        StringBuilder sb = new StringBuilder();
        while((line = bufferedReader.readLine())!= null) {
        	if (++lineNumber <= linesToSkip) {
        		continue;
        	}
        	sb.append(line+"\n");
        }
		return sb.toString();
	}
	
	int random(int min, int max) {
		Random rand = new Random();
		return rand.nextInt(max - min + 1) + min;
	}
	
}